/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dartstools.interfaces;

import dartstools.Theme;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.text.DefaultFormatter;

/**
 *
 * @author Chris
 */
public class DartPanel extends JPanel {

    private JFormattedTextField dartScoreTextField;
    private PlayerPanel parent;
    private int lastDartScore;

    public DartPanel() {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() { // not happy with this method of laying-out
                Dimension vd = new Dimension(0, getHeight());
                Dimension hd = new Dimension(getWidth(), 0);
                dblBtn.setVisible(false);
                trblBtn.setVisible(false);
                vBar.setPreferredSize(vd);
                vBar.setMinimumSize(vd);
                vBar.setMaximumSize(vd);
                vBar.setSize(hd);
                hBar.setPreferredSize(hd);
                hBar.setMinimumSize(hd);
                hBar.setMaximumSize(hd);
                hBar.setSize(hd);
                ((MainGUI) getTopLevelAncestor()).display();
            }

        });
        initComponents();
        lastDartScore = (int) dartScore.getValue();
        dartScoreTextField = ((JSpinner.NumberEditor) dartScore.getEditor()).getTextField();
        dartScoreTextField.setColumns(2);
        dartScoreTextField.setForeground(Theme.FOREGROUND);
        dartScoreTextField.setBackground(Theme.BACKGROUND);
//        dartScoreTextField.setSelectionColor(Theme.SELECTION);
        dartScoreTextField.setBorder(new EmptyBorder(0, 0, 0, 10));
        ButtonGroupListener bgl = new ButtonGroupListener(dartBtns);
        dblBtn.addItemListener(bgl);
        dblBtn.addActionListener(bgl);
        trblBtn.addItemListener(bgl);
        trblBtn.addActionListener(bgl);
        ((DefaultFormatter) dartScoreTextField.getFormatter()).setCommitsOnValidEdit(true);
        dartScoreTextField.setFocusTraversalKeysEnabled(false);
        dartScoreTextField.addKeyListener(new KeyAdapter() {

            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_TAB) {
                    if (e.getModifiersEx() == KeyEvent.SHIFT_DOWN_MASK)
                        getParentPlayerPanel().focusPreviousScoreBox(DartPanel.this);
                    else
                        getParentPlayerPanel().focusNextScoreBox(DartPanel.this);
                }
                else if (e.getKeyCode() == KeyEvent.VK_LEFT)
                    getParentPlayerPanel().focusPreviousScoreBox(DartPanel.this);
                else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
                    getParentPlayerPanel().focusNextScoreBox(DartPanel.this);
                else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    ((MainGUI) getTopLevelAncestor()).focusNextPlayerPanel(parent);
                    getParentPlayerPanel().logScore();
                }
                else if (e.getKeyCode() == KeyEvent.VK_D && dblBtn.isEnabled() && dblBtn.isVisible()) {
                    boolean invert = !dblBtn.isSelected();
                    if (((int) dartScore.getValue()) <= 20)
                        dartBtns.clearSelection();
                    dblBtn.setSelected(invert);
                }
                else if (e.getKeyCode()
                        == KeyEvent.VK_T && trblBtn.isEnabled() && trblBtn.isVisible()) {
                    boolean invert = !trblBtn.isSelected();
                    if (((int) dartScore.getValue()) <= 20)
                        dartBtns.clearSelection();
                    trblBtn.setSelected(invert);
                }

                SwingUtilities.invokeLater(
                        new Runnable() {

                            @Override
                            public void run() {
                                dartScoreTextField.setText(dartScoreTextField.getText().replaceAll("[^\\d]", ""));
                            }

                        });
            }

        });
    }

    public int getSpinnerValue() {
        return (int) getSpinner().getValue();
    }

    public boolean requiresModifierSelection() {
        return getSpinnerValue() > 20
                && isDivisibleBy(getSpinnerValue(), 2)
                && isDivisibleBy(getSpinnerValue(), 3)
                && !(dblBtn.isSelected() || trblBtn.isSelected());
    }

    public void resetField() {
        dartScore.setValue(0);
    }

    public int getModifier() {
        if (this.dblBtn.isSelected()) {
            return 2;
        }
        else if (this.trblBtn.isSelected()) {
            return 3;
        }
        else {
            return 1;
        }
    }

    public void focus(boolean selectText) {
        dartScoreTextField.requestFocusInWindow();
        if (selectText) {
            dartScoreTextField.addFocusListener(new FocusAdapter() {

                @Override
                public void focusGained(FocusEvent evt) {
                    SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            dartScoreTextField.selectAll();
                        }

                    });
                }

            });
        }
    }

    public JSpinner getSpinner() {
        return dartScore;
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        dartBtns = new javax.swing.ButtonGroup();
        dartScore = new javax.swing.JSpinner();
        trblBtn = new javax.swing.JRadioButton();
        dblBtn = new javax.swing.JRadioButton();
        vBar = new javax.swing.JPanel();
        hBar = new javax.swing.JPanel();

        setOpaque(false);

        dartScore.setFont(new Font(Theme.FONT_FAMILY, Font.BOLD, Theme.FONT_LARGE));
        dartScore.setModel(new javax.swing.SpinnerNumberModel(0, 0, 60, 1));
        dartScore.setEditor(new javax.swing.JSpinner.NumberEditor(dartScore, ""));
        dartScore.setFocusCycleRoot(true);
        dartScore.setNextFocusableComponent(dblBtn);
        dartScore.setOpaque(false);
        dartScore.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                dartScoreStateChanged(evt);
            }
        });

        trblBtn.setBackground(new java.awt.Color(0, 171, 83));
        dartBtns.add(trblBtn);
        trblBtn.setFont(new Font(Theme.FONT_FAMILY, Font.PLAIN, Theme.FONT_SMALL));
        trblBtn.setForeground(new java.awt.Color(255, 255, 255));
        trblBtn.setText("T 00");
        trblBtn.setBorder(javax.swing.BorderFactory.createEmptyBorder(3, 3, 3, 3));
        trblBtn.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        trblBtn.setFocusPainted(false);
        trblBtn.setMargin(new java.awt.Insets(2, 5, 2, 5));
        //trblBtn.setVisible(false);

        dblBtn.setBackground(new java.awt.Color(241, 51, 39));
        dartBtns.add(dblBtn);
        dblBtn.setFont(new Font(Theme.FONT_FAMILY, Font.PLAIN, Theme.FONT_SMALL));
        dblBtn.setForeground(new java.awt.Color(255, 255, 255));
        dblBtn.setText("D 00");
        dblBtn.setBorder(javax.swing.BorderFactory.createEmptyBorder(3, 3, 3, 3));
        dblBtn.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        dblBtn.setFocusPainted(false);
        dblBtn.setMargin(new java.awt.Insets(2, 5, 2, 5));
        dblBtn.setNextFocusableComponent(trblBtn);
        //dblBtn.setVisible(false);

        vBar.setBackground(new java.awt.Color(255, 51, 51));
        vBar.setOpaque(false);

        javax.swing.GroupLayout vBarLayout = new javax.swing.GroupLayout(vBar);
        vBar.setLayout(vBarLayout);
        vBarLayout.setHorizontalGroup(
            vBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );
        vBarLayout.setVerticalGroup(
            vBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );

        hBar.setBackground(new java.awt.Color(255, 51, 51));
        hBar.setOpaque(false);

        javax.swing.GroupLayout hBarLayout = new javax.swing.GroupLayout(hBar);
        hBar.setLayout(hBarLayout);
        hBarLayout.setHorizontalGroup(
            hBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );
        hBarLayout.setVerticalGroup(
            hBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(hBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(vBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(dblBtn, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(dartScore)
                    .addComponent(trblBtn, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(dartScore, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(1, 1, 1)
                        .addComponent(dblBtn)
                        .addGap(1, 1, 1)
                        .addComponent(trblBtn))
                    .addComponent(vBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(hBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private boolean isDivisibleBy(int dividend, int divisor) {
        return dividend % divisor == 0
                && dividend / divisor <= 20 // has to be a number on the board
                && dividend * divisor != 0; // return false for any zeroes
    }

    private void dartScoreStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_dartScoreStateChanged
        dartScoreTextField.requestFocusInWindow();
        dartBtns.clearSelection();
        int score = (int) dartScore.getValue();
        boolean dBy2 = isDivisibleBy(score, 2);
        boolean dBy3 = isDivisibleBy(score, 3);
        dblBtn.setText("D: " + (dBy2 ? score / 2 : ""));
        dblBtn.setVisible(dBy2);
        trblBtn.setText("T: " + (dBy3 ? score / 3 : ""));
        trblBtn.setVisible(dBy3);
        if (score > 20) {
            if (dBy2 && !dBy3)
                dblBtn.setSelected(true);
            else if (!dBy2 && dBy3)
                trblBtn.setSelected(true);
            else if (!dBy2 && !dBy3) { // impossible score, e.g. 23
                int nextVal = lastDartScore < score ? score + 1 : score - 1;
                dartScore.setValue(nextVal);
            }
        }
        lastDartScore = score;
        System.out.println(score);
    }//GEN-LAST:event_dartScoreStateChanged

    private PlayerPanel getParentPlayerPanel() {
        if (this.parent == null) {
            this.parent = getParentPlayerPanel(this);
        }
        return this.parent;
    }

    private PlayerPanel getParentPlayerPanel(Component current) {
        if (current.getParent() == null) {
            throw new IllegalStateException("Could not find parent PlayerPanel");
        }
        else if (current.getParent() instanceof PlayerPanel) {
            return (PlayerPanel) current.getParent();
        }
        else {
            return getParentPlayerPanel(current.getParent());
        }
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.ButtonGroup dartBtns;
    private javax.swing.JSpinner dartScore;
    private javax.swing.JRadioButton dblBtn;
    private javax.swing.JPanel hBar;
    private javax.swing.JRadioButton trblBtn;
    private javax.swing.JPanel vBar;
    // End of variables declaration//GEN-END:variables

    private class ButtonGroupListener implements ActionListener, ItemListener {

        private ButtonGroup bg;
        private boolean itemStateChanged = false;

        public ButtonGroupListener(ButtonGroup bg) {
            this.bg = bg;
        }

        @Override
        public void itemStateChanged(ItemEvent itemEvent) {
            itemStateChanged = true;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (!itemStateChanged && ((Integer) dartScore.getValue()) <= 20)
                bg.clearSelection();
            itemStateChanged = false;
//            DartPanel.this.focus(false);
        }

    }
}
